﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ArivisAccounts.Models;
using WebMatrix.WebData;
using System.Web.Security;

namespace ArivisAccounts.Controllers
{
    [Authorize]
    public class UserController : Controller
    {
        private UserProfilesDbContext dbContext;
        
        //
        // GET: /User/
        public ActionResult Index()
        {
            dbContext = new UserProfilesDbContext();
            var model = dbContext.UserProfiles.Select(EditUserModel.Create);
            return View(model);
        }

        //
        // GET: /User/Create
        [Authorize(Roles = "Admin")]
        public ActionResult Create()
        {
            return View(new RegisterModel());
        }

        //
        // POST: /User/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Admin")]
        public ActionResult Create(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    WebSecurity.Login(model.UserName, model.Password);
                    return RedirectToAction("Index");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", Helper.ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }


        //
        // GET: /User/Edit/5
        public ActionResult Edit(string user)
        {
            EditUserModel model = new EditUserModel();
            model.User = user;
            model.RolesForUser = System.Web.Security.Roles.GetRolesForUser(user);
            model.AllRoles = System.Web.Security.Roles.GetAllRoles();
            return View(model);
        }

        //
        // POST: /User/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Admin")]
        public ActionResult Edit(EditUserModel model)
        {
            if (ModelState.IsValid)
            {
                string[] oldValues = System.Web.Security.Roles.GetRolesForUser(model.User);
                string[] newValues = model.RolesForUser ?? new string[0];

                // make sure we don't remove our own 'Admin'-right
                if (model.User == User.Identity.Name && !newValues.Contains("Admin"))
                {
                    newValues = newValues.Concat(new string[] { "Admin" }).ToArray();
                }

                var removed = oldValues.Except(newValues).ToArray();
                var added = newValues.Except(oldValues).ToArray();

                if (removed.Any())
                    System.Web.Security.Roles.RemoveUserFromRoles(model.User, removed);
                if (added.Any())
                    System.Web.Security.Roles.AddUserToRoles(model.User, added);
            }

            return RedirectToAction("Index");
        }


        //
        // GET: /Account/ResetPassword/1
        [Authorize(Roles = "Admin")]
        public ActionResult ResetPassword(string user)
        {
            dbContext = new UserProfilesDbContext();
            var userProfile = dbContext.UserProfiles.FirstOrDefault(x => x.UserName == user);
            if (userProfile == null)
                return this.RedirectToAction("Index");

            var model = new ResetPasswordModel();
            model.UserId = userProfile.UserId;
            model.UserName = userProfile.UserName;

            return View(model);
        }

        //
        // POST: /Account/ResetPassword
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ResetPassword(ResetPasswordModel model)
        {
            if (ModelState.IsValid)
            {
                // ChangePassword will throw an exception rather than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                try
                {
                    string token = WebSecurity.GeneratePasswordResetToken(model.UserName);
                    changePasswordSucceeded = WebSecurity.ResetPassword(token, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }
                if (changePasswordSucceeded)
                {
                    return RedirectToAction("Index");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        protected override void Dispose(bool disposing)
        {
            if (dbContext != null)
                dbContext.Dispose();

            base.Dispose(disposing);
        }
    }
}
